package cn.opencodes.framework.autoconfigure;


import static com.google.common.collect.Lists.newArrayList;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.springframework.context.annotation.Bean;
import org.springframework.web.bind.annotation.RequestMethod;

import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.builders.ResponseMessageBuilder;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.ApiKey;
import springfox.documentation.service.AuthorizationScope;
import springfox.documentation.service.Contact;
import springfox.documentation.service.ResponseMessage;
import springfox.documentation.service.SecurityReference;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.contexts.SecurityContext;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
import cn.opencodes.framework.autoconfigure.properties.AlphaProperties;
import cn.opencodes.framework.autoconfigure.properties.SwaggerProperties;
import cn.opencodes.framework.core.shiro.AuthcSecretFilter;
import cn.opencodes.framework.core.shiro.AuthcTokenFilter;

import com.github.xiaoymin.swaggerbootstrapui.annotations.EnableSwaggerBootstrapUI;
/**
 * Swagger配置
 * @author HJ
 */
@EnableSwagger2
@EnableSwaggerBootstrapUI
public class SwaggerConfiguration {
	
    @Bean
    public Docket createRestApi(AlphaProperties props, SwaggerProperties swaConfig) {
    	//全局响应
    	List<ResponseMessage> responseMessageList = new ArrayList<>();
    	Map<Integer, String> messages = swaConfig.getMessages();
    	for (int key : messages.keySet()) {
    		responseMessageList.add(new ResponseMessageBuilder().code(key).message(messages.get(key)).build());
		}
    	//
        return new Docket(DocumentationType.SWAGGER_2)
    		.globalResponseMessage(RequestMethod.GET, responseMessageList)
            .globalResponseMessage(RequestMethod.POST, responseMessageList)
            .globalResponseMessage(RequestMethod.PUT, responseMessageList)
            .globalResponseMessage(RequestMethod.DELETE, responseMessageList)
            .groupName( swaConfig.getGroupName() )
            .apiInfo( apiInfo(swaConfig) )
            .select()
            //加了ApiOperation注解的类，才生成接口文档
            //.apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
            //包下的类，才生成接口文档
            .apis( RequestHandlerSelectors.basePackage(swaConfig.getBasePackage()) )
            .paths( PathSelectors.any() )
            .build()
            .securitySchemes( securitySchemes(props) )
            .securityContexts( securityContexts(props) );
    }

    private ApiInfo apiInfo(SwaggerProperties swaConfig) {
        return new ApiInfoBuilder()
            .title(swaConfig.getTitle())
            .description(swaConfig.getDescription())
            .termsOfServiceUrl(swaConfig.getServiceUrl())
            .contact(new Contact(swaConfig.getAuthor(), swaConfig.getWebsit(), swaConfig.getEmail()))
            .version(swaConfig.getVersion())
            .build();
    }

    private List<ApiKey> securitySchemes(AlphaProperties props) {
    	String appKey = AuthcSecretFilter.HEADER_APP_KEY;
    	String appSecret = AuthcSecretFilter.HEADER_SECRET_KEY;
    	String token = AuthcTokenFilter.HEADER_TOKEN_KEY;
    	if (props.isOpenSecret() && props.isOpenToken()) {
    		 return newArrayList(
	            new ApiKey(appKey, appKey, "header"),
	            new ApiKey(appSecret, appSecret, "header"),
	            new ApiKey(token, token, "header")
	         );
		}else if (props.isOpenSecret()) {
        	 return newArrayList(
	            new ApiKey(appKey, appKey, "header"),
	            new ApiKey(appSecret, appSecret, "header")
	         );
		}else if (props.isOpenToken()) {
			 return newArrayList(
				new ApiKey(token, token, "header")
	         );
		}else{
			return null;
		}
    }
    
    private List<SecurityContext> securityContexts(AlphaProperties props) {
        return newArrayList(
                SecurityContext.builder()
                      .securityReferences(defaultAuth(props))
                      .forPaths(PathSelectors.regex("/*.*"))
                      .build()
        );
    }

    private List<SecurityReference> defaultAuth(AlphaProperties props) {
    	String appKey = AuthcSecretFilter.HEADER_APP_KEY;
    	String appSecret = AuthcSecretFilter.HEADER_SECRET_KEY;
    	String token = AuthcTokenFilter.HEADER_TOKEN_KEY;
        AuthorizationScope[] authorizationScopes = 
        		new AuthorizationScope[]{new AuthorizationScope("global", "accessEverything")};
        if (props.isOpenSecret() && props.isOpenToken()) {
        	return newArrayList(
    			new SecurityReference(appKey, authorizationScopes),
    			new SecurityReference(appSecret, authorizationScopes),
    			new SecurityReference(token, authorizationScopes)
    		);
        }else if (props.isOpenSecret()) {
        	return newArrayList(
    			new SecurityReference(appKey, authorizationScopes),
    			new SecurityReference(appSecret, authorizationScopes)
    		);
        }else if (props.isOpenToken()) {
        	return newArrayList(
        		new SecurityReference(token, authorizationScopes)
        	);
		}else{
			return null;
		}
    }

}